This section examines the crucial elements in providing the Security Token Service functionality for providing a SAML Holder-Of-Key token. The components that will be discussed are.
Security Domain
The STS requires a JBoss security domain be configured. The jboss-web.xml descriptor declares a named security domain,"JBossWS-trust-sts" to be used by this service for authentication. This security domain requires two properties files and the addition of a security-domain declaration in the JBoss server configuration file.
For this scenario the domain needs to contain user alice, password clarinet, and role friend. See the listings below for jbossws-users.properties and jbossws-roles.properties. In addition the following XML must be added to the JBoss security subsystem in the server configuration file. Replace "SOME_PATH" with appropriate information.
<security-domain name="JBossWS-trust-sts">
<authentication>
<login-module code="UsersRoles" flag="required">
<module-option name="usersProperties" value="/SOME_PATH/jbossws-users.properties"/>
<module-option name="unauthenticatedIdentity" value="anonymous"/>
<module-option name="rolesProperties" value="/SOME_PATH/jbossws-roles.properties"/>
</login-module>
</authentication>
</security-domain>
jboss-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-web PUBLIC"-//JBoss//DTD Web Application 2.4//EN" ">
<jboss-web>
<security-domain>java:/jaas/JBossWS-trust-sts</security-domain>
</jboss-web>
jbossws-users.properties
# A sample users.properties filefor use with the UsersRolesLoginModule
alice=clarinet
jbossws-roles.properties
# A sample roles.properties filefor use with the UsersRolesLoginModule
alice=friend
STS's implementation class
The Apache CXF's STS, SecurityTokenServiceProvider, is a web service provider that is compliant with the protocols and functionality defined by the WS-Trust specification. It has a modular architecture. Many of its components are configurable or replaceable and there are many optional features that are enabled by implementing and configuring plug-ins. Users can customize their own STS by extending from SecurityTokenServiceProvider and overriding the default settings. Extensive information about the CXF's STS configurable and pluggable components can be found here.
This STS implementation class, SampleSTSHolderOfKey, is a POJO that extends from SecurityTokenServiceProvider. Note that the class is defined with a WebServiceProvider annotation and not a WebService annotation. This annotation defines the service as a Provider-based endpoint, meaning it supports a more messaging-oriented approach to Web services. In particular, it signals that the exchanged messages will be XML documents of some type. SecurityTokenServiceProvider is an implementation of the javax.xml.ws.Provider interface. In comparison the WebService annotation defines a (service endpoint interface) SEI-based endpoint which supports message exchange via SOAP envelopes.
As was done in the HolderOfKeyImpl class, the WSS4J annotations EndpointProperties and EndpointProperty are providing endpoint configuration for the CXF runtime. The first EndpointProperty statements declares the Java properties file that contains the (Merlin) crypto configuration information. WSS4J reads this file and extra required information for message handling. The last EndpointProperty statement declares the STSHolderOfKeyCallbackHandler implementation class. It is used to obtain the user's password for the certificates in the keystore file.
In this implementation we are customizing the operations of token issuance and their static properties.
StaticSTSProperties is used to set select properties for configuring resources in the STS. You may think this is a duplication of the settings made with the WSS4J annotations. The values are the same but the underlaying structures being set are different, thus this information must be declared in both places.
The setIssuer setting is important because it uniquely identifies the issuing STS. The issuer string is embedded in issued tokens and, when validating tokens, the STS checks the issuer string value. Consequently, it is important to use the issuer string in a consistent way, so that the STS can recognize the tokens that it has issued.
The setEndpoints call allows the declaration of a set of allowed token recipients by address. The addresses are specified as reg-ex patterns.
TokenIssueOperation has a modular structure. This allows custom behaviors to be injected into the processing of messages. In this case we are overriding the SecurityTokenServiceProvider's default behavior and performing SAML token processing. CXF provides an implementation of a SAMLTokenProvider which we are using rather than writing our own.
Learn more about the SAMLTokenProvider here.
package org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsholderofkey;
import org.apache.cxf.annotations.EndpointProperties;
import org.apache.cxf.annotations.EndpointProperty;
import org.apache.cxf.sts.StaticSTSProperties;
import org.apache.cxf.sts.operation.TokenIssueOperation;
import org.apache.cxf.sts.service.ServiceMBean;
import org.apache.cxf.sts.service.StaticService;
import org.apache.cxf.sts.token.provider.SAMLTokenProvider;
import org.apache.cxf.ws.security.sts.provider.SecurityTokenServiceProvider;
import javax.xml.ws.WebServiceProvider;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* User: rsearls
* Date: 3/14/14
*/
@WebServiceProvider(serviceName = "SecurityTokenService",
portName = "UT_Port",
targetNamespace = "http://docs.oasis-open.org/ws-sx/ws-trust/200512/",
wsdlLocation = "WEB-INF/wsdl/holderofkey-ws-trust-1.4-service.wsdl")
//be sure to have dependency on org.apache.cxf module when on AS7, otherwise Apache CXF annotations are ignored
@EndpointProperties(value = {
@EndpointProperty(key = "ws-security.signature.properties", value = "stsKeystore.properties"),
@EndpointProperty(key = "ws-security.callback-handler", value = "org.jboss.test.ws.jaxws.samples.wsse.policy.trust.stsholderofkey.STSHolderOfKeyCallbackHandler")
})
public class SampleSTSHolderOfKey extends SecurityTokenServiceProvider
{
public SampleSTSHolderOfKey() throws Exception
{
super();
StaticSTSProperties props = new StaticSTSProperties();
props.setSignatureCryptoProperties("stsKeystore.properties");
props.setSignatureUsername("mystskey");
props.setCallbackHandlerClass(STSHolderOfKeyCallbackHandler.class.getName());
props.setEncryptionCryptoProperties("stsKeystore.properties");
props.setEncryptionUsername("myservicekey");
props.setIssuer("DoubleItSTSIssuer");
List<ServiceMBean> services = new LinkedList<ServiceMBean>();
StaticService service = new StaticService();
service.setEndpoints(Arrays.asList(
"https://localhost:(\\d)*/jaxws-samples-wsse-policy-trust-holderofkey/HolderOfKeyService",
"https://\\[::1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-holderofkey/HolderOfKeyService",
"https://\\[0:0:0:0:0:0:0:1\\]:(\\d)*/jaxws-samples-wsse-policy-trust-holderofkey/HolderOfKeyService"
));
services.add(service);
TokenIssueOperation issueOperation = new TokenIssueOperation();
issueOperation.getTokenProviders().add(new SAMLTokenProvider());
issueOperation.setServices(services);
issueOperation.setStsProperties(props);
this.setIssueOperation(issueOperation);
}
}
Crypto properties and keystore files
WSS4J's Crypto implementation is loaded and configured via a Java properties file that contains Crypto configuration data. The file contains implementation-specific properties such as a keystore location, password, default alias and the like. This application is using the Merlin implementation. File stsKeystore.properties contains this information.
File servicestore.jks, is a Java KeyStore (JKS) repository. It contains self signed certificates for myservicekey and mystskey. Self signed certificates are not appropriate for production use.
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=stsspass
org.apache.ws.security.crypto.merlin.keystore.file=stsstore.jks